package http;

import java.io.*;
import java.util.*;
import java.net.*;


import data.DataHandler;
import data.DataQueue;
import model.MailQueue;

public class HTTPserver extends Thread {

    final static int PORT = 5309;
    final static String SERVER_ADDRESS = "127.0.0.1";// "192.168.3.116"; Virtual Machine's Tap0 Interface
    final static String CRLF = "\r\n";
    private ServerSocket ss;
    private String currentLine = null;
    private String emailData = null;
    public static DataQueue obDataQueue;
    private String from;
    private String to;
    private String subject;
    private String delay;
    private String smtp;
    private String body;

    public HTTPserver(Socket client) {
        this.client = client;

    }
    private PrintStream output = null;
    private BufferedReader input = null;
    private Socket client = null;

    //In this method we process the packet and petitions to send to the smtp server
    public void run() {
        try {
            System.out.println("The Client " + client.getInetAddress() + ":" + client.getPort() + " is connected");
            System.out.println("...Server Online, waiting for connections");

            output = new PrintStream(client.getOutputStream());
            input = new BufferedReader(new InputStreamReader(client.getInputStream()));

            String currentLine = input.readLine();
            System.out.println("Received Packet:" + currentLine);
            if (requestType(currentLine)) {
                if (requestProcessing(currentLine).equals("/index.html") || requestProcessing(currentLine).equals("/")) {
                    // The default home page
                    System.out.println("...Loading web form");
                    sendResponse(true, INDEX_PAGE);
                } else if (requestProcessing(currentLine).equals("/statusweb.html")) {
                    System.out.println("...loading web status");
                    //The status page
                    sendResponse(true, STATUS_PAGE);
                } else {
                    emailData = getForm(requestProcessing(currentLine));
                    if (emailData != null && emailData.length() > 0
                            && emailData.contains("textfieldFrom") && emailData.contains("textfieldTo")
                            && emailData.contains("textfieldSubject") && emailData.contains("textfieldSMTP")
                            && emailData.contains("textfieldDelay") && emailData.contains("textareaMessage")) {
                        /*We only call this part after client submit the mail data, at the second GET method request*/
                        System.out.println("...loading web data");
                        DataHandler smtpHandler = new DataHandler(emailData, obDataQueue);
                        if (smtpHandler.getSMTPValidation()) {
                            //The email is valid
                            //Send response to the client about the successfully sending message
                            sendResponse(true, SUCCESS_PAGE);
                        } else {
                            //Send response FAILED to client
                            sendResponse(true, FAILED_PAGE);
                        }
                    } else {
                        sendResponse(false, WRONG_PAGE);
                    }
                }
            }//end if
            else {
                System.out.println("Invalid request");
                sendResponse(false, STATUS_PAGE);
            }
            System.out.println("Closing HTTP connection...");
        } catch (Exception e) {
            System.out.println("Exception happens");
            e.printStackTrace();
        }
    }

    public synchronized void setDataQueue(DataQueue obDataQueue) {
        this.obDataQueue = obDataQueue;
    }

    public synchronized DataQueue getDataQueue() {
        return obDataQueue;
    }
    //This method is used to decode the data from the web interface

    private String getForm(String text) {
        String emailFields = "";
        try {
            emailFields = URLDecoder.decode(text, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return emailFields;
    }

    //Method used to check in the received query is GET. In that case, it returns true, otherwise false
    private Boolean requestType(String request) {
        if (request.regionMatches(true, 0, "GET ", 0, 4)) {
            return true;
        } else {
            return false;
        }
    }

    //with this method we obtain the requested file in the query
    private String requestProcessing(String request) {
        try {
            int fsp = request.indexOf(' ');
            int nsp = request.indexOf(' ', fsp + 1);
            String file = request.substring(fsp + 1, nsp);
            if (file.equals("/index.htm")) {
                return null;
            } else {
                return file;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }//end of method

    //method to reply with a code 200 OK
    private String reply(boolean isOk) {
        String reply = "";
        if (isOk) {
            reply = "HTTP/1.1 200 OK";
        } else {
            reply = "HTTP/1.1 404 Not Found";
        }
        return reply;
    }
    private final int INDEX_PAGE = 0;
    private final int STATUS_PAGE = 1;
    private final int WRONG_PAGE = 2;
    private final int SUCCESS_PAGE = 3;
    private final int FAILED_PAGE = 4;

    private void sendResponse(boolean isOk, int request) throws Exception {
        String responseString = "";
        switch (request) {
            case INDEX_PAGE:
                responseString = headHTML() + bodyHTML(null);
                break;
            case STATUS_PAGE:
                responseString = headHTML() + staticBodyHTML() + publishEmailData();
                break;
            case WRONG_PAGE:
                responseString = headHTML() + bodyHTMLWrongPage();
                break;
            case SUCCESS_PAGE:
                responseString = headHTML() + bodyHTML("The message has been sent");
                break;
            case FAILED_PAGE:
                responseString = headHTML() + bodyHTML("You must insert valid addresses");
                break;
        }
        output.println(reply(isOk));
        output.println(addHeader(responseString.length()));
        output.println(responseString);
        output.flush();
        output.close();
        input.close();
        client.close();
    }

    private String addHeader(int contentLength) {
        Date d = new Date();
        String header = "Date: " + d.toString() + CRLF + "Content-Type: text/html" + CRLF + "Content-Length: " + contentLength + CRLF;
        return header;
    }

    private String headHTML() {
        String head = "<HTML>"
                + "<HEAD>"
                + "<TITLE>IK2213 Web Mail</TITLE>"
                + "<META http-equiv=Content-Type content=\"text/html; charset=UTF8\">"
                + "<META content=\"MSHTML 6.00.2900.5512\" name=GENERATOR>"
                + "<script type=\"text/javascript\">"
                + "</script>"
                + "</HEAD>";
        return head;
    }

    private String bodyHTMLWrongPage() {
        String body = "<BODY>+"
                + "<H1 align=center>Webmail Application</H1>"
                + "<H4 align=center>The page that you reques is not available, please go to <a href=\"http://"+SERVER_ADDRESS+":5309/index.html\">http://"+SERVER_ADDRESS+":5309/index.html</a></H4>"
                + "</BODY>";
        return body;
    }

    private String bodyHTML(String message) {
        String body = "";
        if (message == null) {
            body = "<BODY>";
        } else {
            body = "<BODY onload='alert(\"" + message + "\");'>";
        }
        body += "<H1 align=center>Webmail Application</H1>" + CRLF + "<FORM name=formWebmail method=\"get\" action=\"http://"+SERVER_ADDRESS+":5309\">" + CRLF + "<table>" + CRLF + "<tr>" + CRLF + "<td><b>From</b></td>" + CRLF + "<td><INPUT value=\"type your email\" name=textfieldFrom onClick=javascript:this.value=\"\"></td>" + CRLF + "</tr>" + CRLF + "<tr>" + CRLF + "<td><b>To</b></td>" + CRLF + "<td><INPUT value=\"type the recipient\" name=textfieldTo onClick=javascript:this.value=\"\"></td>" + CRLF + "</tr>" + CRLF + "<tr>" + CRLF + "<td><b>Subject</b></td>" + CRLF + "<td><INPUT value=\"Welcome to Webmail\" name=textfieldSubject onClick=javascript:this.value=\"\"></td>" + CRLF + "</tr>" + CRLF + "<tr>" + CRLF + "<td><b>SMTP Server</b></td>" + CRLF + "<td><INPUT value=mail.ik2213.lab name=textfieldSMTP onClick=javascript:this.value=\"\"></td>" + CRLF + "</tr>" + CRLF + "<tr>" + CRLF + "<td><b>Delay</b></td>" + CRLF + "<td><INPUT value=0 name=textfieldDelay onClick=javascript:this.value=\"\"></td>" + CRLF + "</tr>" + CRLF + "<tr>" + "<td valign=top><b>Message</b></td>" + CRLF + "<td><TEXTAREA name=textareaMessage rows=20 cols=80 onClick=javascript:this.value=\"\">Write your message</TEXTAREA><BR></td>" + CRLF + "</tr>" + CRLF + "</table>" + CRLF + "<INPUT type=submit value=Submit name=btnSubmit> <INPUT type=reset value=Reset name=btnReset>" + CRLF + "<H4 align=center>Go To <a href=\"http://"+SERVER_ADDRESS+":5309/statusweb.html\">Status Delivery Page</a></H4>" + CRLF + "</FORM>" + CRLF + "</BODY>" + "</HTML>";

        return body;
    }

    private String staticBodyHTML() {
        String body = "<body> "
                + "<H1 align=center>Status Mail Web</H1>"
                + "<H4 align=center>Back To <a href=\"http://"+SERVER_ADDRESS+":5309/index.html\">Main Mail Page</a></H4> "
                + "<table width=\"100%\" border=\"1\" align=\"center\">"
                + "<tr><th width=12%><b><H4 align=center>From</H4></b></th>"
                + "<th width=12%><b><H4 align=center >To</H4></b></th>"
                + "<th width=12%><b><H4 align=center>Subject</H4></b></th>"
                + "<th width=18%><b><H4 align=center>Sending Time</H4></b></th>"
                + "<th width=18%><b><H4 align=center>Delivery Time</H4></b></th>"
                + "<th width=12%><b><H4 align=center>Status</H4></b></th>"
                + "<th width=16%><b><H4 align=center>Details</H4></b></th>"
                + "</tr>";
        return body;
    }

    //Now, we implement the code for the dynamic data, answering the object from DataQueue.java
    private String publishEmailData() {
        String body = "";
        int counter = obDataQueue.numberOfMessages();
        int i = 0;
        Hashtable obQueueHashMail = obDataQueue.getMailQueue();
        Enumeration e = obQueueHashMail.keys();
        MailQueue container = null;

        while (e.hasMoreElements()) {
            String key = (String) e.nextElement();
            container = (MailQueue) obQueueHashMail.get(key);
            String obStrFrom = container.getSender();
            String obStrTo = container.getReceiver();
            String obStrSubject = container.getSubject();
            String obStrDeliveryTime = container.getDeliveryTime();
            String obStrSubmitTime = container.getSubmitDate();
            String obStrSendingTime = container.getSendingTime();
            String obStrDeliveryDetail = container.getDeliveryDetail();
            int obIntDeliveryStatus = container.getDeliveryStatus();
            String obStatus = "";
            if (obIntDeliveryStatus == 0) {
                obStatus = "SENDING PROCESS";
            } else if (obIntDeliveryStatus == 1) {
                obStatus = "DELIVERED";
            } else {
                obStatus = "FAILED";
            }
            String obStrTime = "";
            if (obStrSubmitTime != null) {
                obStrTime = obStrSubmitTime + ",  request delay to send on " + obStrSendingTime;
            } else {
                obStrTime = obStrSendingTime;
            }

            if (obStrDeliveryTime == null) {
                obStrDeliveryTime = "Not Available";
            }

            body += "<tr>"
                    + "<td width=\"12%\"><H5 align=center>" + obStrFrom + "</H5></td> "
                    + "<td width=\"12%\"><H5 align=center >" + obStrTo + "</H5></td> "
                    + "<td width=\"12%\"><H5 align=center>" + obStrSubject + "</H5></td>"
                    + "<td width=\"18%\"><H5 align=center>" + obStrTime + "</H5></td>"
                    + "<td width=\"18%\"><H5 align=center >" + obStrDeliveryTime + "</H5></td>"
                    + "<td width=\"12%\"><H5 align=center >" + obStatus + "</H5></td>"
                    + "<td width=\"16%\"><H5 align=center>" + obStrDeliveryDetail + "</H5></td>"
                    + "</tr>";

        }//end of for
        body += "</table></body></html>";
        return body;
    }//end of method

    public static void main(String args[]) throws Exception {

        ServerSocket Server = new ServerSocket(PORT, 10, InetAddress.getByName(SERVER_ADDRESS));
        System.out.println("TCPServer Waiting for client on port" + PORT);
        obDataQueue = new DataQueue();

        while (true) {
            Socket connected = Server.accept();
            (new HTTPserver(connected)).start();
        }
    }
}//class end

